%{
#include <stdio.h>	
#include "ast.h"

extern int yylex();
extern AST_NODE * ast;

%}

%union
{
	TABLE_ENTRY * symb_tab_node;
  AST_NODE * ast_node;
}


%token KW_INT KW_FLOAT KW_BOOL KW_CHAR KW_IF KW_THEN KW_ELSE KW_WHILE KW_DO KW_INPUT      
%token KW_RETURN KW_OUTPUT OPERATOR_LE OPERATOR_GE OPERATOR_EQ OPERATOR_NE OPERATOR_AND  
%token OPERATOR_OR <symb_tab_node>TK_IDENTIFIER <symb_tab_node>LIT_INTEGER <symb_tab_node>LIT_FLOA <symb_tab_node>LIT_FALSE <symb_tab_node>LIT_TRUE <symb_tab_node>LIT_CHAR <symb_tab_node>LIT_STRING    
%token TOKEN_ERROR   


%left OPERATOR_OR;
%left OPERATOR_AND;
%left OPERATOR_EQ OPERATOR_NE ;
%left '>' OPERATOR_GE ;
%left '<' OPERATOR_LE;
%left '+' '-';
%left '*' '/';

%%

program:  		declaration_global program {ast = create_node(LIST,$1,NULL,NULL,NULL,NULL);}|
              func program |
               ;

declaration:		TK_IDENTIFIER ':' tipo {$$ = find_entry(yylval);};

declaration_global:	declaration decl_array_option ';';

decl_array_option:	'['LIT_INTEGER']' |
		     	 ;

tipo:  KW_INT |
			KW_FLOAT |
			KW_CHAR |
			KW_BOOL;

func:			header declaration_local body ';'; 

header:			declaration '('parameters')';

parameters:		declaration parameters_rest |
			 ;

parameters_rest:	',' declaration parameters_rest |
			 ;

declaration_local:	declaration ';' declaration_local |
			 ;

body:			'{'list_simple_command'}';

list_simple_command: 	simple_command rest_list_command;

rest_list_command: 	';' simple_command rest_list_command |
                    	 ;

simple_command:		body |
			assignment |
			input |
			output |
			return |
			if |
			while |
			 ;

assignment:		TK_IDENTIFIER array_option '=' expression;

input:			KW_INPUT TK_IDENTIFIER;

output:			KW_OUTPUT output_list;

output_list:		LIT_STRING output_list_rest |
			expression output_list_rest;

output_list_rest:	','LIT_STRING output_list_rest |
			','expression output_list_rest |
			 ;

return:			KW_RETURN expression;

if:			KW_IF '('expression')' KW_THEN simple_command else_option;

else_option:		KW_ELSE simple_command |
			 ;

while:			KW_WHILE '('expression')' simple_command;

expression:		elem | 
			expression op expression |
			'('expression')';

elem:			TK_IDENTIFIER array_option |
			func_call |
			LIT_INTEGER |
			LIT_FLOA |
			LIT_TRUE |
			LIT_FALSE|
		        LIT_CHAR;

array_option:		'['expression']' |
			 ;

op:			'+'|
			'-'|
			'*'|
			'/'|
			'<'|
			'>'|
			OPERATOR_LE |
			OPERATOR_GE |
			OPERATOR_EQ |
			OPERATOR_NE |
			OPERATOR_AND |
			OPERATOR_OR;

func_call:		TK_IDENTIFIER '('arguments')';

arguments:		elem arguments_rest |
			 ;

arguments_rest:		',' elem arguments_rest |
			 ;

%%

int yyerror(char *mens)
{
	printf("Erro Sintático na linha %d\n", getLineNumber());
	return 0;
}
